
#include "StdAfx.h"
#include "CodecConverter.h"


CCodecConverter::CCodecConverter(int codecFrom, int codecTo, BOOL bAudio)
{
	m_nFromCodec    = codecFrom;
	m_nToCodec      = codecTo;
	m_pDecCodec     = NULL;
	m_pEncCodec     = NULL;
	m_pFrame        = NULL;
	m_pDecContext   = NULL;
	m_pEncContext   = NULL;
	m_pImgConvertCtx = NULL;
	m_bAudio        = bAudio;
}
BOOL CCodecConverter::SetScaling(int fromW, int fromH, PixelFormat fromPixFmt, int toW, int toH, PixelFormat toPixFmt)
{
	m_pImgConvertCtx = CFFMpegInstance::GetInstance()->f_sws_getContext(fromW, fromH, fromPixFmt, 
		toW, toH, toPixFmt, SWS_BICUBIC, 
		NULL, NULL, NULL);

	if(m_pImgConvertCtx == NULL)
		return FALSE;

	return TRUE;
}
CCodecConverter::~CCodecConverter()
{
	if (m_pImgConvertCtx)
	{
		CFFMpegInstance::GetInstance()->f_sws_freeContext(m_pImgConvertCtx);
		m_pImgConvertCtx = NULL;
	}

	if(m_pEncContext)
	{
		delete m_pEncContext;
		m_pEncContext = NULL;
	}
	if (m_pDecContext)
	{
		delete m_pDecContext;
		m_pDecContext = NULL;
	}
	if (m_pFrame)
	{
		CFFMpegInstance::GetInstance()->f_av_free(m_pFrame);
		m_pFrame = NULL;
	}
}
BOOL CCodecConverter::Init()
{
	CFFMpegInstance::GetInstance()->f_lock();
	CFFMpegInstance::GetInstance()->f_avcodec_init();

	// Register all codecs
	CFFMpegInstance::GetInstance()->f_avcodec_register_all();
	CFFMpegInstance::GetInstance()->f_av_register_all();

	m_pEncCodec = CFFMpegInstance::GetInstance()->f_avcodec_find_encoder((CodecID)m_nToCodec);

	if (m_pEncCodec == NULL)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	m_pEncContext = new struct AVCodecContext();
	
	if (m_pEncContext == NULL)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	m_pDecCodec = CFFMpegInstance::GetInstance()->f_avcodec_find_decoder((CodecID)m_nFromCodec);

	if (m_pDecCodec == NULL)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	m_pDecContext = new struct AVCodecContext();

	if (m_pDecContext == 0)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	CFFMpegInstance::GetInstance()->f_avcodec_get_context_defaults(m_pEncContext);
	CFFMpegInstance::GetInstance()->f_avcodec_get_context_defaults(m_pDecContext);

	if (m_bAudio == FALSE)
	{
		m_pEncContext->codec_type = CODEC_TYPE_VIDEO;
		m_pEncContext->bit_rate = 1000000;
		m_pEncContext->width = 320;
		m_pEncContext->height = 240;
		m_pEncContext->time_base.den = 10;
		m_pEncContext->time_base.num = 1;
		m_pEncContext->gop_size = 10;
		m_pEncContext->qcompress = 0.9f;
		m_pEncContext->pix_fmt = PIX_FMT_YUV420P;

		m_pDecContext->codec_type = CODEC_TYPE_VIDEO;
		m_pDecContext->bit_rate = 0;
		m_pDecContext->width = 0;
		m_pDecContext->height = 0;
		m_pDecContext->time_base.den = 10;
		m_pDecContext->time_base.num = 1;
		m_pDecContext->pix_fmt = PIX_FMT_YUVJ420P;
	}
	else
	{
		m_pEncContext->codec_type = CODEC_TYPE_AUDIO;

		m_pEncContext->bit_rate = 128000;
		m_pEncContext->sample_rate = 11025;
		m_pEncContext->channels = 1;
		m_pEncContext->bits_per_raw_sample = 16;
		m_pEncContext->bits_per_coded_sample = 16;

		//m_pEncContext->bits_per_raw_sample = 8;
		//m_pEncContext->bits_per_coded_sample = 8;
		//m_pEncContext->block_align = 1;
		//m_pEncContext->time_base.num = 1;
		m_pEncContext->sample_fmt = SAMPLE_FMT_S16;
		
		m_pDecContext->codec_type = CODEC_TYPE_AUDIO;
		m_pDecContext->bit_rate = 128000;
		m_pDecContext->sample_rate = 8000;
		m_pDecContext->channels = 1;

		//m_pDecContext->bits_per_raw_sample = 16;
		//m_pDecContext->bits_per_coded_sample = 16;
		//m_pDecContext->block_align = 1;
		m_pDecContext->time_base.den = 10;
		m_pDecContext->time_base.num = 1;
		m_pDecContext->sample_fmt = SAMPLE_FMT_S16;
	}

	if (CFFMpegInstance::GetInstance()->f_avcodec_open(m_pEncContext, m_pEncCodec) < 0)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	if (CFFMpegInstance::GetInstance()->f_avcodec_open(m_pDecContext, m_pDecCodec) < 0)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	m_pFrame = CFFMpegInstance::GetInstance()->f_avcodec_alloc_frame();
	if (m_pFrame == NULL)
	{
		CFFMpegInstance::GetInstance()->f_unlock();
		return FALSE;
	}

	CFFMpegInstance::GetInstance()->f_unlock();
	return TRUE;
}

int CCodecConverter::convertCodec(unsigned char* fromBuf, int inBufSize, unsigned char* toBuf, int outBufSize)
{
	int nBytesConvert = 0;
	if (m_pFrame == NULL)
		return 0;
	if (m_bAudio)
	{
		int out_size = 0, len = 0;
		short * samples = NULL;
		int frame_size = 0;

		frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
		samples = (short*)malloc(frame_size * 2 );

		out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
		len = CFFMpegInstance::GetInstance()->f_avcodec_decode_audio2(m_pDecContext, (short *)samples, &out_size, fromBuf, inBufSize);
		if (len <= 0 )
		{
			free(samples);
			return 0;
		}
		
		/*memcpy(toBuf, samples, len);
		nBytesConvert = len;
		free(samples);
		return nBytesConvert*/;

		len = CFFMpegInstance::GetInstance()->f_avcodec_encode_audio(m_pEncContext, toBuf, outBufSize, samples);
		if (len <= 0)
		{
			free(samples);
			return 0;
		}
		nBytesConvert = len;
		free(samples);
	}
	else
	{
		int b_got_picture = 0;
		long nBytes = CFFMpegInstance::GetInstance()->f_avcodec_decode_video(m_pDecContext, m_pFrame, &b_got_picture,
		fromBuf, inBufSize);

		if (nBytes <= 0 || (b_got_picture == 0))
			return 0;

		//int width = m_pDecContext->width;
		//int height = m_pDecContext->height;
		//
		//if(m_pImgConvertCtx == NULL)
		//	SetScaling(width, height, PIX_FMT_YUVJ420P, width, height, PIX_FMT_YUV420P);

		//uint8_t *picture_buf;


		//int size = CFFMpegInstance::GetInstance()->f_avpicture_get_size(PIX_FMT_YUV420P, width, height) * 2;

		//picture_buf = new uint8_t[size];

		//if (!picture_buf) {
		//	return NULL;
		//}

		//CFFMpegInstance::GetInstance()->f_avpicture_fill((AVPicture *)m_pFrame, picture_buf,
		//	PIX_FMT_YUV420P, width, height);
		/////////////////////////////////////////////////////////////////////////////////////////////

		//if(m_pImgConvertCtx)
		//	CFFMpegInstance::GetInstance()->f_sws_scale(m_pImgConvertCtx, m_pFrame->data, 
		//	m_pFrame->linesize, 0, 
		//	height, m_pFrame->data, m_pFrame->linesize);

		m_pFrame->pts = __int64(0x8000000000000000);
		nBytes = CFFMpegInstance::GetInstance()->f_avcodec_encode_video(m_pEncContext, toBuf, outBufSize, m_pFrame);
		if (nBytes < 0) {
			return 0;
		}
		else
			nBytesConvert = nBytes;
	}
	return nBytesConvert;
}